/**
 * Author(s): xuming.Wong <xuming.Wong@gmail.com>
 * Origin source from MaNGOS(GPL2).
 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
 */

#include "WorldRunnable.h"

#include "WorldDatabase.h"
#include "World.h"
#include "Timer.h"
#include "BattleGroundManager.h"
#include "MapManager.h"
#include "WorldSocketManager.h"

namespace PQMaind
{

	
	void WorldRunnable::run()
	{
		// Init new SQL thread for the world database
		// let thread do safe mySQL requests (one connection call enough)
		SWorldDB.ThreadStart();
		SWorld.InitResultQueue();

		uint32 realCurrTime=0;
		uint32 realPrevTime=getMilliSecondTime();

		 // used for balanced full tick time length near WORLD_SLEEP_CONST
		uint32 prevSleepTime = 0;
		
		// While the world not stop, update the world
		while(!PQCore::World::IsStoped()){
			PQCore::World::incLoopCounter();
			realCurrTime = getMilliSecondTime();

			uint32 deltaT = getMSTimeDiff(realPrevTime,realCurrTime);
			SWorld.Update(deltaT);//main task

			realPrevTime = realCurrTime;

			// deltaT (D0) include time of previous sleep (d0) + tick time (t0)
			// we want that next d1 + t1 == WORLD_SLEEP_CONST
			// we can't know next t1 and then can use (t0 + d1) == WORLD_SLEEP_CONST requirement
			// d1 = WORLD_SLEEP_CONST - t0 = WORLD_SLEEP_CONST - (D0 - d0) = WORLD_SLEEP_CONST + d0 - D0
			if (deltaT <= WORLD_SLEEP_CONST+prevSleepTime){
				prevSleepTime = WORLD_SLEEP_CONST+prevSleepTime-deltaT;
				PQCore::Thread::Sleep(prevSleepTime);
			}else{
				prevSleepTime = 0;
			}
			
		}

		//exist world
		SWorld.KickAll();//save and kick all players
		SWorld.UpdateSessions(1); // real players unload required UpdateSessions call

		// unload battleground templates before different singletons destroyed
		SBattleGroundMgr.DeleteAllBattleGrounds();

		SMapMgr.UnloadAll();// unload all grids (including locked in memory)

		SWorldSocketMgr.StopNetwork();
		SWorldDB.ThreadStart();
		SWorldDB.ThreadEnd();

	}


}
